<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>箭头函数</title>
</head>

<body>
    <script>
        // 箭头函数和普通函数的区别 
        // 1. 箭头函数语法上比普通函数更加简洁（ES6中每一种函数都可以使用形参赋值默认值和剩余运算符）
        /* function fn(x) {
            return function (y) {
                return
                x + y
            }
        }
        let fn = x => y => x + y; */

        // 2. 箭头函数没有自己的 this，它里面的 this 是继承函数所处的上下文的 this。
        // 使用 call/apply 等任何方式都无法改变 this 的指向
        /* let obj = {
            name: "OBJ"
        };

        function fn1() {
            console.log(this);
        }
        fn1.call(obj);
        let fn2 = () => {
            console.log(this);
        }
        fn2.call(obj);
        document.body.onclick = () => {
            // this:window 不是当前操作的 body 了
            console.log(this);
        }
        document.body.onclick = function () {
            // this:body
            // arr.sort(function (a, b) {
            // this.window 回调函数中的 this 一般都是 window
            arr.sort((a, b) => {
                return a - b;
            })
        } */

        // 回调函数：把一个函数 B 作为实参传递给另外一个函数 A，函数 A 在执行的时候
        // 可以把传递过来的函数 B 去执行（执行 N 次，可传值，可改 this）
        /* function each(arr, callBack) {
            // callback:function(item,index){}
            for (let i = 0; i < arr.length; i++) {
                // let item = arr[i],
                // index = i; 
                // callBack(item, index);
                // callBack(arr[i], i);
                // callBack.call(arr, arr[i], i);
                let flag = callBack.call(arr, arr[i], i);
                if (flag === false) {
                    break;
                }
            }
        }
        each([10, 20, 30, 40], function (item, index) {
            // this: 原始操作数组
            if (index > 1) {
                return false;
            }
        }) */

        // 3. 箭头函数中没有 arguments (类数组)，只能基于 ...ARG 获取传递的参数集合（数组）
        /* let fn = (...arg) => {
            // console.log(arguments); // Uncaught ReferenceError: arguments is not defined 
            console.log(arg);
        }
        fn(10, 20, 30); */


        // 4. 箭头函数不能被 new 执行（因为：箭头函数没有 this 也没有 prototype）
        /* function Fn() {
            this.x = 100;
        }
        Fn.prototype.getX = function () {}
        let f = new Fn(); */

        let Fn = () => {
            this.x = 200;
        }
        let f = new Fn(); // Uncaught TypeError: Fn is not a constructor

        // 思考题？
        // each
        let arr = [10, 20, 30, 'AA', 40];
        obj = {};
        arr = arr.each(function (item, index) {
            // this:obj (each 第二个参数不传，this 是 window 即可)
            if (isNaN(item)) {
                return false; // 如果 return 的是 false，则结束当前数组的循环
            }
            return item * 10; //  返回的结果是啥，就把数组中当前项替换成啥？
        }, obj)

        // replace 重写这个方法，实现和内置一模一样的效果（只需要考虑 replace([REG],[CALLBACK])这种传参格式的处理）
        let str = "janine2018janin2019";
        str = str.replace(/janine/g,function(...arg){
            // arg 中存储了每一次大正则匹配的信息和小分组匹配的信息
            return '@'; // 返回的是啥把当前正则匹配的内容替换成啥
        })
   </script>
</body>

</html>